package completableFuture;

import java.util.concurrent.*;
import java.util.function.Supplier;

public class Create {

    /**
     * 运行一个不需要返回结果的异步任务
     *
     */
    public static void main1(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            // Simulate a long-running Job
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            System.out.println("I'll run in a separate thread than the main thread.");
        });
        future.get();
    }

    /**
     * 运行一个携带返回结果的异步任务
     *
     */
    public static void main2(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "Result of the asynchronous computation";
        });

// Block and get the result of the Future
        String result = future.get();
        System.out.println(result);


    }

    /**
     * 创建一个线程池并从线程池当中获取一个线程执行异步任务
     *
     */
    public static void main3(String[] args) throws ExecutionException, InterruptedException {
        Executor executor = Executors.newFixedThreadPool(10);
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "Result of the asynchronous computation";
        }, executor);

        System.out.println(future.get());

    }

    /**
     * thenApply() 可以使用 thenApply() 处理和改变CompletableFuture的结果。
     * 持有一个Function<R,T>作为参数。Function<R,T>是一个简单的函数式接口，接受一个T类型的参数，产出一个R类型的结果。
     * whatsYourNameFuture 会开辟一个线程运行 不会阻塞主线线程 运行完后会通知 greetingFuture 线程继续运行
     */
    public static void main4(String[] args) throws ExecutionException, InterruptedException {

        // Create a CompletableFuture
        CompletableFuture<String> whatsYourNameFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "Rajeev";
        });

        System.out.println("whatsYourNameFuture is run");
        System.out.println("whatsYourNameFuture is run");
        System.out.println("whatsYourNameFuture is run");

        CompletableFuture<String> greetingFuture = whatsYourNameFuture.thenApply(name -> {
            return "Hello " + name;
        });

        System.out.println("whatsYourNameFuture is run2");
        System.out.println("whatsYourNameFuture is run2");
        System.out.println("whatsYourNameFuture is run2");

        System.out.println(greetingFuture.get());

        System.out.println("----------------------------------");

        CompletableFuture<String> welcomeText = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "Rajeev";
        }).thenApply(name -> {
            return "Hello " + name;
        }).thenApply(greeting -> {
            return greeting + ", Welcome to the CalliCoder Blog";
        });

        System.out.println(welcomeText.get());

    }

    /**
     * thenAccept() 和 thenRun() 都和supplyAsync在相同的线程中
     * 如果你不想从你的回调函数中返回任何东西，仅仅想在Future完成后运行一些代码片段，你可以使用thenAccept()和 thenRun()方法，
     * 这些方法经常在调用链的最末端的最后一个回调函数中使用。
     * CompletableFuture.thenAccept()持有一个Consumer<T>，返回一个CompletableFuture<Void>。它可以访问CompletableFuture的结果：
     * thenRun() 不能访问任务中的内容需要直接执行代码片段
     *
     *
     *
     */
    public static void main5(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            return "product";
        }).thenAccept(product -> {
            System.out.println("返回字符串的长度" + product.length());
        });


        CompletableFuture.supplyAsync(() -> {
            return "product";
        }).thenRun(() -> {
            System.out.println("无法获取任务的返回值，只能做后续处理");

        });
    }

    /**
     * thenApplyAsync 传入一个线程池他会从线程池中获取另一个线程执行下面的逻辑
     *
     */
    public static void main6(String[] args) {

        System.out.println("现在主线程id"+Thread.currentThread().getId());

        Executor executor = Executors.newFixedThreadPool(3);
        CompletableFuture.supplyAsync(() -> {
            System.out.println("现在线程id为"+Thread.currentThread().getId());
            return "Some result";
        },executor).thenApplyAsync(result -> {
            System.out.println("现在线程id为"+Thread.currentThread().getId());
            System.out.println(result);
            return "Processed Result";
        }, executor);

    }

}
